package cn.itsource.wechat.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpUtil;
import cn.itsource.basic.exception.BusinessException;
import cn.itsource.basic.util.AjaxResult;
import cn.itsource.basic.util.RedisService;
import cn.itsource.org.domain.User;
import cn.itsource.org.mapper.UserMapper;
import cn.itsource.org.vo.LoginVO;
import cn.itsource.org.vo.UserInfo;
import cn.itsource.wechat.domain.*;
import cn.itsource.wechat.mapper.WxUserMapper;
import cn.itsource.wechat.service.IWeChatService;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
@Slf4j
public class WeChatServiceImpl implements IWeChatService {

    @Autowired
    private WechatProperties wechatProperties;

    @Autowired
    private WxUserMapper wxUserMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisService redisService;

    @Override
    public String tologin() {
        /**  一.去获取临时票据授权码  */

        //1.告诉微信我要去拿code
        //参数 1.appid 2.redirect_uri
        //authorization-code-url:https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_login&state=%s#wechat_redirect

        //2.拼接出需要重定向跳转的url
        String redirectUri = String.format(wechatProperties.getAuthorizationCodeUrl(),
                wechatProperties.getAppId(), wechatProperties.getRedirectUri(), IdUtil.fastSimpleUUID());

        System.out.println(redirectUri);
        //去重定向
        return "redirect:" + redirectUri;
    }

    @Override
    public String callback(String code) {

        /** 二:通过code和   其他参数  获取token*/
        //token-url: "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code"
        //1.拼接获取token的路径
        String getTokenUrl = String.format(wechatProperties.getTokenUrl(), wechatProperties.getAppId(), wechatProperties.getAppSecrect(), code);

        System.out.println(getTokenUrl);
        //2.访问路径
        String tokenResult = HttpUtil.get(getTokenUrl);
        log.info("token结果,{}",tokenResult); //返回是json格式

        //3.获取fastjson转成对象
        WechatTokenDto wechatTokenDto = JSONObject.parseObject(tokenResult, WechatTokenDto.class);
        log.info("wechatTokenDto对象,{}",wechatTokenDto);

        /** 三, 通过token获取第三方微信的用户信息*/
        //userinfo-url: "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s"
        String getUserInfoUrl = String.format(wechatProperties.getUserinfoUrl(), wechatTokenDto.getAccess_token(), wechatTokenDto.getOpenid());

        //1.调用地址,获取用户的json
        String userInfoResult = HttpUtil.get(getUserInfoUrl);
        log.info("userInfoResult结果,{}",userInfoResult); //返回是json格式

        //2.获取fastjson转成对象
        WechatUserInfoDto userInfoDto = JSONObject.parseObject(userInfoResult, WechatUserInfoDto.class);
        log.info("userInfoDto对象,{}",userInfoDto);


        //-----------上面的微信的三方操作已经全部完成 ,接下来是pethome自己系统的绑定业务了\-----------------
        //t_wxuser  微信用户表    t_user  用户表

        //情况1  没有wxuser
        //1.通过openid查询wxuser,如果查不到,直接去绑定页面

        String openid = userInfoDto.getOpenid();
        WxUser wxUser = wxUserMapper.selectOneByOpenid(openid);
        if (wxUser == null){
            //bean拷贝
            WxUser copyWxUser = BeanUtil.copyProperties(userInfoDto, WxUser.class);
            //微信信息入库
            wxUserMapper.insertSelective(copyWxUser);
            //重定向到绑定页面
            return "redirect:http://bugtracker.itsource.cn:8082/binder.html?openid="+openid;
        }

        //情况2,wxUser存在  user_id不存在
        Long userId = wxUser.getUser_id();
        if (userId == null){
            //重定向到绑定页面
            return "redirect:http://bugtracker.itsource.cn:8082/binder.html?openid="+openid;
        }

        //情况3, wxUser存在,user_id也存在, 但是user查不到
        //情况4,user也有 ,但是手机号为空
        User user = userMapper.selectByPrimaryKey(userId);
        if (user == null || StringUtils.isBlank(user.getPhone())){
            //重定向到绑定页面
            return "redirect:http://bugtracker.itsource.cn:8082/binder.html?openid="+openid;
        }

        //情况5,什么都有,跳转到首页
        //1.1redis里面存token=用户信息
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername(userInfoDto.getNickname());

        String token = IdUtil.fastSimpleUUID();
        redisService.setStringKeyAndValue(token,userInfo,30);

        //跳转到首页index.html  //自己处理中文问题
        return "redirect:http://bugtracker.itsource.cn:8082/index.html?token="+token+"&username="+userInfoDto.getNickname();
    }

    /**
     * BinderDto
     *     //验证码
     *     private String code;
     *     //openid 微信加密号
     *     private String openid;
     *     //手机号
     *     private String phone;
     * @param dto
     * @return
     */
    @Override
    public AjaxResult binder(BinderDto dto) {
        //1.验证验证码是否正确
        //获取Redis的验证码,如果不存在,已失效
        String code = redisService.getKeyObjectValue(dto.getPhone(), String.class);
        Optional.ofNullable(code).orElseThrow(() -> new BusinessException("验证码已经失效,请重新获取"));

        //2.到了这里默认wxuser就有值了,但是user有可能没有值
        //根据手机号查询user对象
        User byPhoneUser = userMapper.findByPhone(dto.getPhone());

        Long userId = null;
        UserInfo userInfo = null;
        if (byPhoneUser == null){
            //先要对user进行入库
            User user = new User();
            user.setPhone(dto.getPhone());
            user.init();

            //入库
            userMapper.insertSelective(user);
            userId = user.getId();
            //copy
            userInfo = BeanUtil.copyProperties(user, UserInfo.class);
        }else {
            userId = byPhoneUser.getId();
            //copy
            userInfo = BeanUtil.copyProperties(byPhoneUser, UserInfo.class);
        }

        //通过openid查询之前就有的wxuser ,给wxuser绑定 user_id
        WxUser wxUser = wxUserMapper.selectOneByOpenid(dto.getOpenid());
        wxUser.setUser_id(userId);
        wxUserMapper.updateByPrimaryKeySelective(wxUser);


        //存redis
        //3.把数据保存到redis key :token (搞个uuid就行了)  封装vo对象(返回前端的专用对象)
        String token = IdUtil.fastSimpleUUID();
        redisService.setStringKeyAndValue(token,userInfo,30);

        //封装返回的页面vo数据
        LoginVO loginVO = new LoginVO(token, userInfo);

        //返回成果
        return AjaxResult.createSuccess(loginVO);
    }

}
